#pragma once
#include "genbase.hpp"
#include "protosimpleparser.hpp"

class GenHandler : public GenBase {
 public:
  static bool Gen(ServiceInfo &serviceInfo) {
    if (not ExecCmd("mkdir -p ./handler")) return false;
    for (auto rpcInfo : serviceInfo.rpc_infos_) {
      string file = "./handler/" + rpcInfo.cpp_file_name_;
      if (IsFileExist(file)) {
        continue;
      }
      if (not genRpcHandler(serviceInfo, rpcInfo, file)) return false;
    }
    if (not genHandler(serviceInfo)) return false;
    return true;
  }

 private:
  static bool genRpcHandler(ServiceInfo &serviceInfo, RpcInfo rpcInfo, string file) {
    string prefix = serviceInfo.handler_file_prefix_;
    string serviceName = serviceInfo.service_name_;
    stringstream out;
    out << R"(#include "../)" + prefix + R"(handler.h")" << endl;
    out << endl;
    out << "int " + serviceName + "Handler::" + rpcInfo.rpc_name_ + "(" + rpcInfo.request_name_ + " &request, " +
               rpcInfo.response_name_ + " &response) {"
        << endl;
    out << R"(  // TODO)" << endl;
    out << "  return 0;" << endl;
    out << "}" << endl;
    return GenFile(file, out.str());
  }
  static bool genHandler(ServiceInfo &serviceInfo) {
    string file = serviceInfo.handler_file_prefix_ + "handler.h";
    string rpcHandler;
    string rpcHandlerStatement;
    string rpcNames;
    for (size_t i = 0; i < serviceInfo.rpc_infos_.size(); i++) {
      auto rpcInfo = serviceInfo.rpc_infos_[i];
      rpcNames += "\"" + rpcInfo.rpc_name_ + "\"";
      rpcHandler += "    RPC_HANDLER(\"" + rpcInfo.rpc_name_ + "\", " + rpcInfo.rpc_name_ + ", " +
                    rpcInfo.request_name_ + ", " + rpcInfo.response_name_ + ", req, resp);";
      rpcHandlerStatement += "  int " + rpcInfo.rpc_name_ + "(" + rpcInfo.request_name_ + " &request, " +
                             rpcInfo.response_name_ + " &response);";
      if (i != serviceInfo.rpc_infos_.size() - 1) {
        rpcNames += ", ";
        rpcHandler += "\n";
        rpcHandlerStatement += "\n";
      }
    }
    stringstream out;
    out << R"(// Generated by the MyRPC compiler v1.0.0 . DO NOT EDIT!

#pragma once

#include <set>
#include <string>

#include "../../common/log.hpp"
#include "../../common/utils.hpp"
#include "../../core/handler.hpp"
#include "../../core/mysvrclient.hpp"
#include "../../protocol/base.pb.h")"
        << endl;
    out << R"(#include "proto/)" + serviceInfo.handler_file_prefix_ + R"(.pb.h")" << endl;
    out << endl;
    out << "using namespace MySvr::Base;" << endl;
    out << "using namespace " << serviceInfo.cpp_namespace_name_ << ";" << endl;
    out << endl;
    out << R"(class )" + serviceInfo.service_name_ + R"(Handler : public Core::MyHandler {
 public:
  )" + serviceInfo.service_name_ +
               R"(Handler() {
    service_name_ = std::string{")" +
               serviceInfo.service_name_ + R"("};
    rpc_names_ = std::unordered_set<std::string>{)" +
               rpcNames + R"(};
  }
  void MySvrHandler(Protocol::MySvrMessage &req, Protocol::MySvrMessage &resp) {
)" + rpcHandler +
               R"(
  }
)" + rpcHandlerStatement +
               R"(
};)";
    return GenFile(file, out.str());
  }
};